import io
import random


from django.db import transaction
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django_redis import get_redis_connection
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from rest_framework_simplejwt.views import TokenObtainPairView
from utils.permissions import UserLoginPermissions, AdministratorsPermission, TeacherPermission
from .serializers import *
from utils.tools import MyCaptchaImage, myDESCipher, ThreadImgs
from utils.filters import MyPageNumberPagination
from celery_tasks.email.tasks import send_email_task_active
from celery_tasks.fdfs.tasks import remove_fdfs_resources


class GetRegisterCodeGenericViewSet(GenericViewSet):
    serializer_class = RegisterCodeSerializer

    def create(self, request):
        # 创建验证码
        num = '123456789'
        codes = ''
        for i in range(4):
            code = random.choice(num)
            codes += code
        # 第二步:校验手机号码 ,再发送验证码
        pattern = r'^1[3-9]\d{9}$'
        print(request.data.get('mobile'))
        if request.data.get('mobile') and re.match(pattern, request.data.get('mobile')) is not None:
            # # 调用容联云
            # message = Message().send_message(request.data.get("mobile"),(codes,'5'))

            # 判断验证码是否发送成功
            # if message == 0:
            # 如果发送成功，缓存验证码
            cache = get_redis_connection(alias='verify_codes')  # 用于获取与指定别名“verify_codes”的 Redis 服务器的连接。
            template = f'verify_codes-{request.data.get("mobile")}'  # template = f'verify_codes-{request.data.get(
            # "mobile")}'：此行通过将字符串“verify_codes-”与从请求数据获取的手机号码连接起来，为缓存创建一个模板密钥。
            cache.set(f'{template}', codes, 300)
            # else:
            #     return Response({
            #         'status': 400,
            #         'msg': '验证码发送失败'
            #     })
            return Response({
                'status': 200,
                'msg': '验证码已发送,请在5分钟之内完成验证！'
            })
        else:
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '你输入的手机号码不正确,或者是没有输入手机号码,请重新尝试输入!'
            })


class GetLoginCodeGenericViewSet(GenericViewSet):
    myCaptchaImage = MyCaptchaImage()

    def retrieve(self, request, uuid):
        img, code = self.myCaptchaImage.generate_code()

        img_bytes = io.BytesIO()
        img.save(img_bytes, format='PNG')
        image_bytes = img_bytes.getvalue()  # 图片的字节数据

        cache = get_redis_connection(alias='verify_codes2')
        code_template = f'picturecode_{uuid}'
        cache.set(f'{code_template}', code, 300)
        return HttpResponse(image_bytes, content_type='image/png')


class RegisterGenericViewSet(GenericViewSet):
    """
        传参：username
        password 需AES加密
        mobile 11位
        email 需满足邮箱格式
        code 验证码
    """
    queryset = User.objects.all()
    serializer_class = RegisterSerializer

    def create(self, request):

        # 校验用户名是否存在
        user = self.get_queryset().filter(username=request.data.get("username")).first()
        if user:
            return Response({
                "status": status.HTTP_409_CONFLICT,
                "msg": "该用户已存在，请换一个用户名进行注册",
            })
        # 校验数据是否正确
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        # 校验验证码 如果不正确则返回报错信息
        cache = get_redis_connection(alias='verify_codes')
        template = f'verify_codes-{request.data.get("mobile")}'
        redis_code = cache.get(template)
        if not redis_code:  # 如果redis_code为None
            redis_code = b'11111111111111'
        if redis_code.decode('utf-8') != request.data['code']:
            cache.delete(f'{template}')
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '验证码不正确，请重新输入'
            })
        # 如果正确，则删除验证码
        cache.delete(f'{template}')
        try:
            with transaction.atomic():
                # 创建用户
                user = User(
                    username=request.data.get('username'),
                    first_name='mq' + request.data.get('username'),
                    email=request.data.get('email'),
                    is_active=0
                )
                request.data['password'] = myDESCipher.decrypt_password(request.data.get('password'))
                user.set_password(request.data.get('password'))
                user.save()
                # 创建用户详情
                userdetail = UserDetail(
                    mobile=request.data.get("mobile"),
                    user=user
                )
                userdetail.save()
        except Exception as e:
            # 返回响应告知用户手机号已被注册
            return Response({
                "status": status.HTTP_409_CONFLICT,
                "msg": "该手机号已被注册，请换一个手机号进行注册",
            })
        # 如果一切正常，返回成功响应
        return Response({
            'status': status.HTTP_201_CREATED,
            'msg': '账号已生成，请联系官方客服激活账号！'
        })


class LoginGenericViewSet(TokenObtainPairView):
    """
        return: res_data.status=18为老师组 status=0为管理员
    """
    serializer_class = LoginTokenObtainSerializer

    def post(self, request, *args, **kwargs):
        # 验证码校验
        cache = get_redis_connection(alias='verify_codes2')
        code_template = f'picturecode_{request.data.get("uuid")}'
        #   取出redis里面的验证码
        redis_code = cache.get(code_template)
        if not redis_code:  # 如果redis_code为None
            redis_code = b'11111111111111'
        if redis_code.decode('utf-8').lower() != request.data.get('code').lower():
            cache.delete(f'{code_template}')
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '验证码不正确，请重新输入'
            })
        # 清除验证码
        cache.delete(f'{code_template}')
        # 校验用户信息，获取token
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        try:
            user = serializer.validated_data['user']
        except KeyError:
            return Response({
                "status": status.HTTP_404_NOT_FOUND,
                "msg": "该用户不存在或密码错误"
            })
        # 返回数据给前端
        user_status = user.groups.first().id if user.groups.first() else None
        if user.is_superuser:
            user_status = 0
        response_data = {
            "status": status.HTTP_201_CREATED,
            "res_data": {
                "token": serializer.validated_data['access'],
                "username": user.first_name,
                "user_id": myDESCipher.encryption(str(user.id)),
                "avatar": user.userdetail.avatar if hasattr(user, "userdetail") else '',
                "status": user_status  # 用户组
            }
        }
        return Response(response_data)


class GroupViewSet(ModelViewSet):
    queryset = Group.objects.all().order_by('id')
    serializer_class = GroupSerializer
    pagination_class = MyPageNumberPagination
    permission_classes = [UserLoginPermissions]  # 定义权限类只能用复数

    def get_queryset(self):
        if self.action in ['list', 'retrieve', 'search']:
            return Group.objects.all().order_by('id')
        return Group.objects.all()

    def get_permissions(self):
        """
          Instantiates and returns the list of permissions that this view requires.
         """
        permission_classes = [UserLoginPermissions]
        if self.action in ['create', 'update', 'destroy']:
            permission_classes.append(AdministratorsPermission)
        return [permission() for permission in permission_classes]

    @action(['get'], detail=False)
    def search(self, request):
        """
        :param name（组名称）:
        :return: {
            count:数据总量，
            results：数据列表
        }
        """
        if not request.query_params.get("name"):
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                "msg": "请输入关键字进行查询！"
            })
        group = self.get_queryset().filter(
            Q(name__contains=request.query_params.get("name")))  # Django ORM 的 __contains 查找来执行模糊匹配
        page = self.pagination_class()
        res = page.paginate_queryset(group, request)
        return Response({'count': len(group), 'results': self.get_serializer(res, many=True).data})


class UserViewSet(ModelViewSet):
    queryset = User.objects.all()
    pagination_class = MyPageNumberPagination
    permission_classes = [UserLoginPermissions]
    threadImgs = ThreadImgs()

    def get_serializer(self, *args, **kwargs):
        action_to_serializer = {
            "account": UpdateUserPasswordSerializer,
            "userdetail_update": UpdateUserDetailSerializer,
            "active": ActiveStudentSerializer,
            "not_active_user": NotActiveStudentSerializer,
        }
        serializer_class = action_to_serializer.get(self.action, UserSerializer)
        return serializer_class(*args, **kwargs)

    def get_permissions(self):
        """
          Instantiates and returns the list of permissions that this view requires.
         """
        permission_classes = [UserLoginPermissions]
        if self.action in ['deactive']:
            permission_classes.append(AdministratorsPermission)
        elif self.action in ['resetting', 'check_depart', 'type', 'not_active_stu', 'active']:
            permission_classes.append(TeacherPermission)
        return [permission() for permission in permission_classes]

    def create(self, request, *args, **kwargs):
        return Response(status=status.HTTP_404_NOT_FOUND)

    @action(['get'], detail=False)
    def not_active_user(self, request):
        """
         :param request:
         :return: {
            count：数据总数,
            results:数据列表
        }
        """
        user = User.objects.filter(is_active=0, is_staff=0)

        page = self.pagination_class()
        res = page.paginate_queryset(user, request)
        return Response({'count': len(user), 'results': self.get_serializer(res, many=True).data})

    @action(['put'], detail=False)
    def deactive(self, request):
        try:
            user = User.objects.get(id=myDESCipher.decryption(request.data.get("id")))
        except:
            return Response({
                "status": status.HTTP_404_NOT_FOUND,
                "msg": "该用户信息不存在，无法操作"
            })
        user.is_active = False if user.is_active else True
        user.save()
        return Response({
            "status": status.HTTP_201_CREATED,
            "msg": "操作成功"
        })

    @action(['put'], detail=False)
    def active(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        print(request.data.get("user_id"))
        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                user = User.objects.get(id=request.data.get("user_id"))
            except:
                return Response({
                    "status": status.HTTP_404_NOT_FOUND,
                    "msg": '该用户信息查询不到!'
                })
            user.is_active = 1
            user.save()
            try:
                # 设置普通用户的身份组
                group = Group.objects.get(name='普通用户组')
            except:
                transaction.savepoint_rollback(save_point)
                return Response({
                    "status": status.HTTP_404_NOT_FOUND,
                    "msg": '该群组信息查询不到!'
                })
            else:
                group.user_set.add(user)
            transaction.savepoint_commit(save_point)
        # 发送邮件
        send_email_task_active.delay(user.email, user.username)
        return Response({
            "status": status.HTTP_201_CREATED,
            "msg": '该用户账号已激活!'
        })

    @action(['put'], detail=False)
    def account(self, request):
        try:
            user = User.objects.get(id=request.user.id)
        except:
            return Response({
                'status': status.HTTP_404_NOT_FOUND,
                "msg": "该用户不存在"
            })
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 查看旧密码是否正确
        # 对于前端传的密码进行解密
        old_password = myDESCipher.decrypt_password(request.data['old_password'])  # 得到客户端输入的原密码
        new_password = myDESCipher.decrypt_password(request.data['new_password'])  # 得到客户端输入的新密码
        if user.check_password(old_password):
            # 保存新密码
            user.set_password(new_password)
        else:
            # 错误 返回提示，原密码错误
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'msg': '旧密码错误，请重新输入！'
            })
        # 判断用户是否传了昵称，如果传了则修改
        if request.data.get("first_name"):
            user.first_name = request.data.get("first_name")
        user.save()
        return Response({
            'status': status.HTTP_201_CREATED,
            'msg': '密码修改成功！'
        })

    @action(['put'], detail=False)
    def userdetail_update(self, request):
        # 查用户是否存在
        try:
            user = User.objects.get(id=request.user.id)
        except:
            return Response({
                'status': status.HTTP_404_NOT_FOUND,
                "msg": "该用户不存在"
            })
        # 序列化器校验数据
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        if len(request.FILES.getlist('avatar')) > 0:
            self.threadImgs.circulate_add_file(request.FILES.getlist('avatar'))
        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                # 保存数据
                user.email = request.data.get('email')
                user.save()
                # 检查手机号码是否已存在
                existing_phone = UserDetail.objects.filter(mobile=request.data['mobile']).first()
                if UserDetail.objects.filter(mobile=request.data['mobile'], user_id=request.user.id).first():
                    existing_phone = None  # 本来就上传的自己的手机号
                if existing_phone:
                    # 如果手机号码已存在，返回错误信息
                    return Response({
                        'status': status.HTTP_400_BAD_REQUEST,
                        'msg': '该手机号码已被注册，请更换手机号',
                    })
                # 判断用户是否有详情数据
                if not hasattr(user, 'userdetail'):
                    userdetail = UserDetail.objects.create(
                        avatar=self.threadImgs.image_list[0] if len(self.threadImgs.image_list) > 0 else '',
                        sex=request.data['sex'],
                        age=request.data['age'],
                        mobile=request.data['mobile'],
                        birthday=request.data['birthday'],
                        address=request.data['address'],
                        synopsis=request.data['synopsis'],
                        user_id=request.user.id
                    )
                    userdetail.save()
                # 查询用户详情信息
                userdetail = UserDetail.objects.get(user_id=request.user.id)

                # 删除原来的图片(判断用户是否上传了图片)
                if len(request.FILES.getlist('avatar')) > 0:
                    remove_fdfs_resources.delay(userdetail.avatar)
                userdetail.age = request.data.get('age')
                userdetail.sex = request.data.get('sex')
                userdetail.mobile = request.data.get('mobile')
                userdetail.birthday = request.data.get('birthday')
                userdetail.address = request.data.get('address')
                userdetail.synopsis = request.data.get('synopsis')
                # 如果 image_list 存在数据，则更新 avatar 字段
                if self.threadImgs.image_list and len(self.threadImgs.image_list) > 0:
                    userdetail.avatar = self.threadImgs.image_list[0]
                userdetail.save()
                # 清除图片列表
                self.threadImgs.clear()
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_point)
                # 图片数据删除
                if len(request.FILES.getlist('avatar')) > 0:
                    remove_fdfs_resources.delay(self.threadImgs.image_list[0])
                return Response({
                    'status': status.HTTP_400_BAD_REQUEST,
                    'msg': '信息修改失败',
                })
            else:
                transaction.savepoint_commit(save_point)
            return Response({
                'status': status.HTTP_200_OK,
                'msg': "数据修改成功",
                'avatar': userdetail.avatar,
            })

    @action(['get'], detail=False)
    def info(self, request):
        # 查用户是否存在
        try:
            user = User.objects.get(id=request.user.id)
        except:
            return Response({
                'status': status.HTTP_404_NOT_FOUND,
                "msg": "该用户不存在"
            })

        return Response({
            "status": status.HTTP_201_CREATED,
            "data": UserInfoSerializer(user).data
        })

    @action(['get'], detail=False)
    def get_name(self, request):
        """

        :param request:
        :return:{
            "status": 200,
            "data": {
                "first_name": "",
                "username": ""
            }
        }
        """
        try:
            user = User.objects.get(id=request.user.id)
        except:
            return Response({
                'status': status.HTTP_404_NOT_FOUND,
                "msg": "该用户不存在"
            })
        data = {
            "first_name": user.first_name,
            "username": user.username
        }
        return Response({
            "status": status.HTTP_200_OK,
            "data": data
        })

    @action(['get'], detail=False)
    def check(self, request):
        """
        1. 查未激活的学生 type='0'
        2. 查老师信息 type='1'
        3. 查已经激活的学生 type='2'
        :param username mobile email type(username，mobile，email 可传可不传):
        :return: {
            count：数据总数,
            results:数据列表
        }
        """
        query = Q()
        username = request.query_params.get('username')
        mobile = request.query_params.get('mobile')
        email = request.query_params.get('email')
        type = request.query_params.get('type')

        if request.query_params.get('username'):
            query &= Q(username=username)
        if mobile != None:
            query &= Q(userdetail__mobile=mobile)
        if email != None:
            query &= Q(email=email)

        if type != None and type == '0':
            # 查未激活的学生
            query &= Q(is_staff=0, is_active=0)
        elif type != None and type == '1':
            # 查老师信息
            query &= Q(is_staff=1, is_active=1)
        elif type != None and type == '2':
            # 查已经激活的学生
            query &= Q(is_staff=0, is_active=1)
            query &= ~Q(classes=None)
        user = User.objects.filter(query)
        # # 数据分页

        page = self.pagination_class()
        res = page.paginate_queryset(user, request)
        return Response({'count': len(user), 'results': self.get_serializer(res, many=True).data})


class SendFriendRequestView(APIView):
    permission_classes = [UserLoginPermissions]

    def post(self, request, *args, **kwargs):
        receiver_id = kwargs.get('receiver_id')
        requester = request.user
        if requester.id == receiver_id:
            return Response({"error": "您不能向自己发送好友请求。"}, status=status.HTTP_400_BAD_REQUEST)

        # 检查是否已经是好友
        if Friend.objects.filter(user=requester, friend_id=receiver_id).exists() or \
                Friend.objects.filter(user=receiver_id, friend=requester).exists():
            return Response({"error": "您和此用户已经是好友，不能再发送请求。"}, status=status.HTTP_400_BAD_REQUEST)
        # 检查是否重复发送pending请求
        queryset = FriendRequest.objects.filter(status='pending')
        if queryset:
            if FriendRequest.objects.filter(requester=requester, receiver_id=receiver_id).exists():
                return Response({"error": "好友请求已发送。请勿重复发送"}, status=status.HTTP_400_BAD_REQUEST)
        # 创建好友请求
        FriendRequest.objects.create(requester=requester, receiver_id=receiver_id, status='pending')
        return Response({"message": "好友请求已发送。"}, status=status.HTTP_201_CREATED)


class AcceptFriendRequestView(APIView):
    permission_classes = [UserLoginPermissions]

    def post(self, request, *args, **kwargs):
        friend_id = kwargs.get('request_id')
        requester = request.user
        # 获取请求的用户实例
        friend_user = get_object_or_404(User, id=friend_id)
        try:
            friend_request = FriendRequest.objects.get(
                requester=friend_user,
                receiver=requester,
                status='pending'
            )

            # 确保没有重复好友关系
            if Friend.objects.filter(user=requester, friend=friend_id).exists():
                return Response({"error": "您和此用户已经是好友。"}, status=status.HTTP_400_BAD_REQUEST)

            # 创建双向好友关系
            Friend.objects.bulk_create([
                Friend(user=requester, friend=friend_user),
                Friend(user=friend_user, friend=requester)
            ])

            # 更新好友请求状态
            friend_request.status = 'accepted'
            friend_request.save()

            return Response({"message": "好友请求已接受。"}, status=status.HTTP_200_OK)

        except FriendRequest.DoesNotExist:
            return Response({"error": "好友请求不存在或已被处理。"}, status=status.HTTP_404_NOT_FOUND)


class RejectFriendRequestView(APIView):
    permission_classes = [UserLoginPermissions]

    def post(self, request, *args, **kwargs):
        friend_id = kwargs.get('request_id')
        requester = request.user
        # 获取请求的用户实例
        friend_user = get_object_or_404(User, id=friend_id)
        try:
            friend_request = FriendRequest.objects.get(
                requester=friend_user,
                receiver=requester,
                status='pending'
            )
            friend_request.status = 'rejected'
            friend_request.save()
            return Response({"message": "好友请求已拒绝。"}, status=status.HTTP_200_OK)
        except FriendRequest.DoesNotExist:
            return Response({"error": "好友请求不存在或已被处理。"}, status=status.HTTP_404_NOT_FOUND)


class DeleteFriendView(APIView):
    permission_classes = [UserLoginPermissions]

    def delete(self, request, *args, **kwargs):
        friend_id = kwargs.get('friend_id')
        user = request.user

        try:
            # 删除双向好友关系
            Friend.objects.filter(user=user, friend_id=friend_id).delete()
            Friend.objects.filter(user=friend_id, friend=user).delete()
            # 更新所有相关的好友请求状态为 'rejected'
            FriendRequest.objects.filter(
                (Q(requester=user) & Q(receiver=friend_id)) |
                (Q(requester=friend_id) & Q(receiver=user))
            ).update(status='rejected')
            return Response({"message": "好友已删除。"}, status=status.HTTP_200_OK)
        except Friend.DoesNotExist:
            return Response({"error": "好友关系不存在。"}, status=status.HTTP_404_NOT_FOUND)


class IsFriendView(APIView):
    permission_classes = [UserLoginPermissions]

    def get(self, request, user_id):
        if request.user.id == user_id:
            # 如果请求的用户是自己，返回is_friend为False
            return Response({'is_friend': False})

        try:
            target_user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return Response({'is_friend': False})

        # 检查是否为朋友关系
        is_friend = Friend.objects.filter(user=request.user, friend=target_user).exists()
        return Response({'is_friend': is_friend})


class FriendRequestStatusView(APIView):
    permission_classes = [UserLoginPermissions]

    def get(self, request, user_id):
        try:
            target_user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return Response({'status': 'not_found'}, status=status.HTTP_404_NOT_FOUND)

        # 查询当前用户是发起者或接收者的好友请求
        friend_request = FriendRequest.objects.filter(
            (Q(requester=request.user, receiver=target_user) | Q(requester=target_user, receiver=request.user))
        ).order_by('-id').first()

        if friend_request:
            return Response({'status': friend_request.status})
        else:
            return Response({'status': 'not_found'})


class FriendListView(APIView):
    permission_classes = [UserLoginPermissions]

    def get(self, request, *args, **kwargs):
        user = request.user
        friends = Friend.objects.filter(user=user)
        serializer = FriendSerializer(friends, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


class PendingFriendRequestsView(APIView):
    permission_classes = [UserLoginPermissions]

    def get(self, request, *args, **kwargs):
        user = request.user
        pending_requests = FriendRequest.objects.filter(receiver=user, status='pending')
        serializer = ShowFriendRequest(pending_requests, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

class UserDetailView(APIView):
    def get(self, request, user_id):
        try:
            user_detail = UserDetail.objects.get(user_id=user_id)
            serializer = UserIDDetailSerializer(user_detail)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except UserDetail.DoesNotExist:
            return Response({"error": "User not found"}, status=status.HTTP_404_NOT_FOUND)
